package com.jiutianniao.p2p.acctrans.core.trans;

import java.util.Date;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import com.jiutianniao.p2p.acctrans.core.account.Account;
import com.jiutianniao.p2p.acctrans.core.account.AccountFactory;
import com.jiutianniao.p2p.acctrans.core.constants.AccountTransConst;
import com.jiutianniao.p2p.acctrans.core.dal.model.TransLogDO;
import com.jiutianniao.p2p.acctrans.core.exception.TransException;
import com.jiutianniao.p2p.acctrans.core.service.ServiceBeans;
import com.jiutianniao.p2p.acctrans.core.vo.LockAccountVO;
import com.jiutianniao.p2p.trans.client.enums.AccountActionEnum;
import com.jiutianniao.p2p.trans.client.model.TransInfo;
import com.jiutianniao.p2p.trans.client.result.AccountTransResult;

public abstract class AbstractAccountTrans {

	private static final Logger logger = LoggerFactory
			.getLogger(AbstractAccountTrans.class);

	@Resource
	protected AccountFactory accountFactory;

	@Resource
	protected ServiceBeans serviceBeans;

	/**
	 * 取得贷方账户
	 */
	protected abstract Account fetchCreditAccount(TransInfo transInfo)
			throws TransException;

	/**
	 * 取得借方账户
	 */
	protected abstract Account fetchDebitAccount(TransInfo transInfo)
			throws TransException;

	@Transactional(rollbackFor = TransException.class)
	public AccountTransResult doTransaction(TransInfo transInfo)
			throws TransException {
		AccountTransResult result = new AccountTransResult();

		// 1. 账务交易准备
		Account debitAccount = null;
		Account creditAccount = null;

		debitAccount = fetchDebitAccount(transInfo);
		creditAccount = fetchCreditAccount(transInfo);

		{
			preTransProcessing(transInfo, debitAccount, creditAccount);
			result = transProcessing(transInfo, debitAccount, creditAccount);
			postTransProcessing(result, debitAccount, creditAccount);
		}

		return result;
	}

	/**
	 * 记录交易流水
	 */
	protected void recordTransLog(TransInfo transInfo, Account debitAccount,
			Account creditAccount) throws TransException {

		TransLogDO transLogDO = new TransLogDO();

		// 使用指定的transLogId
		// transLogDO.setTransLogId(transInfo.getTransLogId());

		// credit帐户
		transLogDO.setTransAccountIn(creditAccount.getAccountNo());
		transLogDO.setAccountInType(creditAccount.getAccountType());

		// debit帐户
		transLogDO.setTransAccountOut(debitAccount.getAccountNo());
		transLogDO.setAccountOutType(debitAccount.getAccountType());

		transLogDO.setTransAmount(transInfo.getTransAmount());
		// transLogDO.setTransChannel(transInfo.getChannel().getValue().toString());
		transLogDO.setTransCode(String.valueOf(transInfo.getTransCode()
				.getCode()));
		if (transInfo.getSubTransCode() != null) {
			transLogDO.setSubTransCode(transInfo.getSubTransCode().getCode());
		}

		transLogDO.setTransCurrency(AccountTransConst.RMB_CURRENCY);
		transLogDO.setTransDate(transInfo.getTransDate());
		if (transInfo.getTransDt() == null) {
			transInfo.setTransDt(new Date());
		}
		transLogDO.setTransDt(transInfo.getTransDt());
		transLogDO.setOutDate(transInfo.getOutDate());
		// transLogDO.setTransInstitution(DEFAULT_INSTITUTION);
		transLogDO.setTransMemo(transInfo.getTransMemo());
		transLogDO.setTransOutOrderNo(transInfo.getTransOutOrderNo());
		transLogDO.setVoucherId(transInfo.getVoucherId());

		Long id = serviceBeans.getTransLogService().getTransLogId();
		transLogDO.setTransLogId(id);
		this.serviceBeans.getTransLogService().saveTransLog(transLogDO);
		transInfo.setTransLogId(id);
	}

	/**
	 * 获取账户包装供处理
	 */
	protected Account fetchAccount(String accountNo, AccountActionEnum action,
			TransInfo transInfo) throws TransException {
		LockAccountVO lockAccountVO = new LockAccountVO(accountNo, transInfo,
				action);
		return accountFactory.getAccount(lockAccountVO);
	}

	/**
	 * 账务交易预处理
	 */
	protected void preTransProcessing(TransInfo transInfo,
			Account debitAccount, Account creditAccount) throws TransException {
		debitAccount.setOtherAccount(creditAccount);
		creditAccount.setOtherAccount(debitAccount);
	}

	/**
	 * 账务处理
	 */
	protected AccountTransResult transProcessing(TransInfo transInfo,
			Account debitAccount, Account creditAccount) throws TransException {

		// 1. 记交易流水表
		recordTransLog(transInfo, debitAccount, creditAccount);
		if (logger.isDebugEnabled()) {
			logger.debug("transProcessing() --- 成功记录交易日志表");
		}

		// 2. 借
		debitAccount.debit(transInfo.getTransAmount(), transInfo);
		if (logger.isDebugEnabled()) {
			logger.debug("transProcessing() --- debit帐户成功("
					+ debitAccount.getAccountNo() + ")");
		}

		// 3. 贷
		if (StringUtils.equals(transInfo.getTransAccountIn(),
				transInfo.getTransAccountOut())) {
			// 同账户自转账更新一下本账户记录
			// creditAccount.reload();
		}
		creditAccount.credit(transInfo.getTransAmount(), transInfo);
		if (logger.isDebugEnabled()) {
			logger.debug("transProcessing() --- credit帐户成功("
					+ creditAccount.getAccountNo() + ")");
		}

		return new AccountTransResult();
	}

	/**
	 * 其他处理
	 * 
	 * @param res
	 *            处理信息
	 */
	protected void postTransProcessing(AccountTransResult res,
			Account debitAccount, Account creditAccount) throws TransException {
		res.setSuccess(true);
	}
}
